package com.ruoyi.pack.service.impl;

import java.util.Date;
import java.util.List;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.pack.domain.PackContainer;
import com.ruoyi.pack.domain.PackLocator;
import com.ruoyi.pack.domain.PackContainerOperationLog;
import com.ruoyi.pack.domain.dto.PackContainerInventoryDTO;
import com.ruoyi.pack.domain.dto.PackContainerSummaryDto;
import com.ruoyi.pack.domain.dto.PackMaterialSummaryDto;
import com.ruoyi.pack.mapper.PackContainerMapper;
import com.ruoyi.pack.mapper.PackLocatorMapper;
import com.ruoyi.pack.mapper.PackContainerOperationLogMapper;
import com.ruoyi.pack.service.IPackContainerService;
import com.ruoyi.pack.service.IPackContainerOperationLogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * 器具Service业务层处理
 * 
 * @author ruoyi
 * @date 2024-01-01
 */
@Service
public class PackContainerServiceImpl implements IPackContainerService 
{
    @Autowired
    private PackContainerMapper packContainerMapper;

    @Autowired
    private PackLocatorMapper packLocatorMapper;

    @Autowired
    private PackContainerOperationLogMapper packContainerOperationLogMapper;
    
    @Autowired
    private IPackContainerOperationLogService packContainerOperationLogService;

    /**
     * 查询器具
     * 
     * @param containerId 器具主键
     * @return 器具
     */
    @Override
    public PackContainer selectPackContainerByContainerId(Long containerId)
    {
        return packContainerMapper.selectPackContainerByContainerId(containerId);
    }

    /**
     * 查询器具列表
     * 
     * @param packContainer 器具
     * @return 器具
     */
    @Override
    public List<PackContainer> selectPackContainerList(PackContainer packContainer)
    {
        return packContainerMapper.selectPackContainerList(packContainer);
    }

    /**
     * 新增器具
     * 
     * @param packContainer 器具
     * @return 结果
     */
    @Override
    @Transactional
    public int insertPackContainer(PackContainer packContainer)
    {
        // 设置默认状态
        if (StringUtils.isEmpty(packContainer.getLocationStatus()))
        {
            packContainer.setLocationStatus("1"); // 默认在库
        }
        if (StringUtils.isEmpty(packContainer.getBusinessStatus()))
        {
            packContainer.setBusinessStatus("1"); // 默认正常
        }
        if (StringUtils.isEmpty(packContainer.getPackingStatus()))
        {
            packContainer.setPackingStatus("1"); // 默认空箱
        }
        packContainer.setCreateTime(DateUtils.getNowDate());
        
        int result = packContainerMapper.insertPackContainer(packContainer);
        
        // 记录操作日志
        if (result > 0) {
            recordContainerOperationLog(packContainer.getContainerId(), "1", "新增器具", packContainer.getCurrentWarehouseId());
        }
        
        return result;
    }

    /**
     * 修改器具
     * 
     * @param packContainer 器具
     * @return 结果
     */
    @Override
    @Transactional
    public int updatePackContainer(PackContainer packContainer)
    {
        packContainer.setUpdateTime(DateUtils.getNowDate());
        
        int result = packContainerMapper.updatePackContainer(packContainer);
        
        // 记录操作日志
        if (result > 0) {
            recordContainerOperationLog(packContainer.getContainerId(), "1", "修改器具", packContainer.getCurrentWarehouseId());
        }
        
        return result;
    }

    /**
     * 批量删除器具
     * 
     * @param containerIds 需要删除的器具主键
     * @return 结果
     */
    @Override
    public int deletePackContainerByContainerIds(Long[] containerIds)
    {
        return packContainerMapper.deletePackContainerByContainerIds(containerIds);
    }

    /**
     * 删除器具信息
     * 
     * @param containerId 器具主键
     * @return 结果
     */
    @Override
    public int deletePackContainerByContainerId(Long containerId)
    {
        return packContainerMapper.deletePackContainerByContainerId(containerId);
    }

    /**
     * 根据器具编码查询器具
     * 
     * @param containerCode 器具编码
     * @return 器具
     */
    @Override
    public PackContainer selectPackContainerByContainerCode(String containerCode)
    {
        return packContainerMapper.selectPackContainerByContainerCode(containerCode);
    }

    /**
     * 器具绑定定位器
     * 
     * @param containerId 器具ID
     * @param locatorId 定位器ID
     * @return 结果
     */
    @Override
    @Transactional
    public int bindLocator(Long containerId, Long locatorId)
    {
        // 校验器具和定位器是否可以绑定
        if (!checkCanBindLocator(containerId, locatorId))
        {
            return 0;
        }
        
        // 获取器具信息（用于日志记录）
        PackContainer container = packContainerMapper.selectPackContainerByContainerId(containerId);
        
        int result = packContainerMapper.bindLocator(containerId, locatorId);
        
        // 记录操作日志
        if (result > 0 && container != null) {
            recordContainerOperationLog(containerId, "2", "绑定定位器", container.getCurrentWarehouseId());
        }
        
        return result;
    }

    /**
     * 器具解绑定位器
     * 
     * @param containerId 器具ID
     * @return 结果
     */
    @Override
    @Transactional
    public int unbindLocator(Long containerId)
    {
        // 获取器具信息（用于日志记录）
        PackContainer container = packContainerMapper.selectPackContainerByContainerId(containerId);
        
        int result = packContainerMapper.unbindLocator(containerId);
        
        // 记录操作日志
        if (result > 0 && container != null) {
            recordContainerOperationLog(containerId, "3", "解绑定位器", container.getCurrentWarehouseId());
        }
        
        return result;
    }

    /**
     * 器具批量绑定定位器
     * 
     * @param containerId 器具ID
     * @param locatorIds 定位器ID列表
     * @return 结果
     */
    @Override
    @Transactional
    public int batchBindLocators(Long containerId, Long[] locatorIds)
    {
        if (locatorIds == null || locatorIds.length == 0) {
            return 0;
        }
        
        // 获取器具信息（用于日志记录）
        PackContainer container = packContainerMapper.selectPackContainerByContainerId(containerId);
        
        // 先解绑该器具的所有定位器
        unbindLocator(containerId);
        
        // 批量绑定新的定位器
        int result = packContainerMapper.batchBindLocators(containerId, locatorIds);
        
        // 记录操作日志
        if (result > 0 && container != null) {
            recordContainerOperationLog(containerId, "2", 
                "批量绑定定位器(共" + locatorIds.length + "个)", container.getCurrentWarehouseId());
        }
        
        return result;
    }

    /**
     * 更新器具状态
     * 
     * @param containerId 器具ID
     * @param locationStatus 位置状态
     * @param businessStatus 业务状态
     * @param packingStatus 装箱状态
     * @return 结果
     */
    @Override
    public int updateContainerStatus(Long containerId, String locationStatus, String businessStatus, String packingStatus)
    {
        return packContainerMapper.updateContainerStatus(containerId, locationStatus, businessStatus, packingStatus);
    }

    /**
     * 器具装箱
     * 
     * @param containerId 器具ID
     * @param projectId 项目ID
     * @param materialCode 物料编码
     * @param materialName 物料名称
     * @param materialQuantity 物料数量
     * @param liningScheme 内衬方案
     * @return 结果
     */
    @Override
    @Transactional
    public int packContainer(Long containerId, Long projectId, String materialCode, String materialName, String materialQuantity, String liningScheme)
    {
        // 校验器具是否可以装箱
        if (!checkContainerOperationAllowed(containerId, "pack"))
        {
            return 0;
        }
        
        // 更新器具装箱信息
        int result = packContainerMapper.updateContainerPackingInfo(containerId, "2", projectId, materialCode, materialName, materialQuantity, liningScheme);
        
        return result;
    }

    /**
     * 器具拆箱
     * 
     * @param containerId 器具ID
     * @return 结果
     */
    @Override
    @Transactional
    public int unpackContainer(Long containerId)
    {
        // 校验器具是否可以拆箱
        if (!checkContainerOperationAllowed(containerId, "unpack"))
        {
            return 0;
        }
        
        // 更新器具装箱信息
        int result = packContainerMapper.updateContainerPackingInfo(containerId, "1", null, null, null, null, null);
        
        return result;
    }

    /**
     * 更新器具定位信息
     * 
     * @param containerId 器具ID
     * @param latitude 纬度
     * @param longitude 经度
     * @param uploadTime 上传时间
     * @param locationLogId 定位日志ID
     * @param address 地址
     * @param province 省份
     * @param city 城市
     * @param district 区县
     * @return 结果
     */
    @Override
    public int updateContainerLocationInfo(Long containerId, String latitude, String longitude, String uploadTime, Long locationLogId, String address, String province, String city, String district)
    {
        return packContainerMapper.updateContainerLocationInfo(containerId, latitude, longitude, uploadTime, locationLogId, address, province, city, district);
    }

    /**
     * 库存统计查询
     * 
     * @param packContainer 查询条件
     * @return 库存统计结果
     */
    @Override
    public List<PackContainerInventoryDTO> selectInventoryStatistics(PackContainer packContainer)
    {
        return packContainerMapper.selectInventoryStatistics(packContainer);
    }

    /**
     * 校验器具编码唯一性
     * 
     * @param containerCode 器具编码
     * @return 结果 true-唯一 false-不唯一
     */
    @Override
    public boolean checkContainerCodeUnique(String containerCode)
    {
        PackContainer container = packContainerMapper.selectPackContainerByContainerCode(containerCode);
        return container == null;
    }

    /**
     * 校验器具是否可以绑定定位器
     * 
     * @param containerId 器具ID
     * @param locatorId 定位器ID
     * @return 结果 true-可以绑定 false-不可以绑定
     */
    @Override
    public boolean checkCanBindLocator(Long containerId, Long locatorId)
    {
        // 检查器具是否存在
        PackContainer container = packContainerMapper.selectPackContainerByContainerId(containerId);
        if (container == null)
        {
            return false;
        }
        
        // 检查器具是否已绑定定位器
        if (container.getLocatorId() != null)
        {
            return false;
        }
        
        // 检查定位器是否存在
        PackLocator locator = packLocatorMapper.selectPackLocatorByLocatorId(locatorId);
        if (locator == null)
        {
            return false;
        }
        
        // 检查定位器状态是否正常
        if (!"1".equals(locator.getLocatorStatus()))
        {
            return false;
        }
        
        return true;
    }

    /**
     * 校验器具状态是否可操作
     * 
     * @param containerId 器具ID
     * @param operationType 操作类型
     * @return 结果 true-可操作 false-不可操作
     */
    @Override
    public boolean checkContainerOperationAllowed(Long containerId, String operationType)
    {
        PackContainer container = packContainerMapper.selectPackContainerByContainerId(containerId);
        if (container == null)
        {
            return false;
        }
        
        // 报废状态的器具不能进行任何业务操作
        if ("4".equals(container.getBusinessStatus()))
        {
            return false;
        }
        
        // 装箱操作：只有空箱才能装箱
        if ("pack".equals(operationType))
        {
            return "1".equals(container.getPackingStatus());
        }
        
        // 拆箱操作：只有满箱才能拆箱
        if ("unpack".equals(operationType))
        {
            return "2".equals(container.getPackingStatus());
        }
        
        return true;
    }
    
    /**
     * 记录器具操作日志
     * 
     * @param containerId 器具ID
     * @param operationType 操作类型
     * @param operationDesc 操作描述
     * @param warehouseId 仓库ID
     */
    private void recordContainerOperationLog(Long containerId, String operationType, String operationDesc, Long warehouseId) {
        try {
            PackContainerOperationLog log = new PackContainerOperationLog();
            log.setContainerId(containerId);
            log.setOperationType(operationType);
            log.setOperationDetail(operationDesc);
            log.setOperationTime(new Date());
            log.setWarehouseId(warehouseId);
            
            // 获取当前操作用户信息
            try {
                Long userId = SecurityUtils.getUserId();
                log.setOperatorId(userId);
            } catch (Exception e) {
                // 如果获取用户信息失败，设置为null
                log.setOperatorId(null);
            }
            
            try {
                String username = SecurityUtils.getUsername();
                log.setCreateBy(username);
            } catch (Exception e) {
                // 如果获取用户名失败，设置为默认值
                log.setCreateBy("system");
            }
            
            packContainerOperationLogService.insertPackContainerOperationLog(log);
        } catch (Exception e) {
            // 日志记录失败不影响主要业务逻辑，只记录错误日志
            System.err.println("记录器具操作日志失败: " + e.getMessage());
        }
    }

    /**
     * 器具汇总统计查询
     * 按器具型号、库房、项目、状态分组统计器具数量
     *
     * @param packContainer 查询条件
     * @return 汇总统计结果
     */
    @Override
    public List<PackContainerSummaryDto> selectContainerSummary(PackContainer packContainer)
    {
        return packContainerMapper.selectContainerSummary(packContainer);
    }

    /**
     * 获取器具汇总详情列表
     * 根据汇总条件查询具体的器具列表
     *
     * @param packContainer 查询条件
     * @return 器具列表
     */
    @Override
    public List<PackContainer> selectContainerSummaryDetail(PackContainer packContainer)
    {
        return packContainerMapper.selectContainerSummaryDetail(packContainer);
    }

    /**
     * 物料汇总统计查询
     * 按物料编码、库房、项目、状态分组统计物料数量
     *
     * @param packContainer 查询条件
     * @return 物料汇总统计结果
     */
    @Override
    public List<PackMaterialSummaryDto> selectMaterialSummary(PackContainer packContainer)
    {
        return packContainerMapper.selectMaterialSummary(packContainer);
    }

    /**
     * 获取物料汇总详情列表
     * 根据物料汇总条件查询具体的器具列表
     *
     * @param packContainer 查询条件
     * @return 器具列表
     */
    @Override
    public List<PackContainer> selectMaterialSummaryDetail(PackContainer packContainer)
    {
        return packContainerMapper.selectMaterialSummaryDetail(packContainer);
    }
}